package org.millioncall.yueyoga.common.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.millioncall.yueyoga.admin.model.Authority;
import org.millioncall.yueyoga.admin.model.Resource;
import org.millioncall.yueyoga.admin.service.AuthorityService;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

//自定义资源和权限列表类
public class ZhuwSecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource {
	private static Map<String, Collection<ConfigAttribute>> resourceMap;// 权限和资源对应映射
	private AuthorityService authorityService;

	public ZhuwSecurityMetadataSource(AuthorityService authorityService) {
		this.authorityService = authorityService;
		loadResourceDefine();
	}

	public AuthorityService getAuthorityService() {
		return authorityService;
	}

	public void setAuthorityService(AuthorityService authorityService) {
		this.authorityService = authorityService;
	}

	// 加载所有权限列表
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		if (resourceMap == null) {
			loadResourceDefine();
		}
		Iterator<String> it = resourceMap.keySet().iterator();
		Collection<ConfigAttribute> cas = new HashSet<ConfigAttribute>();
		while (it.hasNext()) {
			String key = it.next();
			cas.addAll(resourceMap.get(key));
		}
		return cas;
	}

	// 加载所有资源与权限的映射map，若要实现动态授权，应在权限改变后手动调用此方法，默认只在登录时加载一次到内存
	public void loadResourceDefine() {
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
		List<Authority> authorities = this.authorityService
				.findByEnabledWithResource(true);// 取出所有的权限（已启用的）

		for (Authority authority : authorities) {// 遍历所有权限
			ConfigAttribute ca = new SecurityConfig(authority.getName());
			List<Resource> resources = authority.getResources();// 取得权限对应的所有资源
			Collection<ConfigAttribute> cas;// 资源对应的权限列表
			for (Resource resource : resources) {
				if (!resource.getEnabled().booleanValue()) {// 如果资源未启用，不进行处理
					continue;
				}
				if (resourceMap.containsKey(resource.getUrl())) {// 如果map中已包含此url
					cas = resourceMap.get(resource.getUrl());
				} else {
					cas = new HashSet<ConfigAttribute>();
				}
				cas.add(ca);
				resourceMap.put(resource.getUrl(), cas);
			}
		}
	}

	// 返回所请求资源所需要的权限
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		if (resourceMap == null) {
			loadResourceDefine();
		}
		HttpServletRequest request = ((FilterInvocation) object).getRequest();
		// 此url是不带参数的
		String url = request.getRequestURI();

		Iterator<String> it = resourceMap.keySet().iterator();
		Collection<ConfigAttribute> cas = new HashSet<ConfigAttribute>();// 创建一个新的权限集合
		PathMatcher matcher = new AntPathMatcher();

		while (it.hasNext()) {
			String resource = it.next();
			if (matcher.match(resource, url)) {
				cas.addAll(resourceMap.get(resource));
			}
		}
		return cas;
	}

	public boolean supports(Class<?> clazz) {
		return true;
	}
}